<template>
  <el-container class="panel-container">
    <el-tabs v-model="activeTab" style="height: 100%;width: 100%;overflow: hidden">
      <el-tab-pane :label="i18nt('designer.hint.widgetSetting')" name="1">
        <el-scrollbar class="setting-scrollbar">

          <template v-if="!!designer.selectedWidget && !designer.selectedWidget.category">
            <el-form :model="optionModel" size="small" label-position="left" label-width="120px" class="setting-form"
                     @submit.prevent>
              <el-collapse v-model="widgetActiveCollapseNames" class="setting-collapse">
                <el-collapse-item name="1" v-if="showCollapse(commonProps)"
                                  :title="i18nt('designer.setting.commonSetting')">
                  <template v-for="(editorName, propName) in commonProps">
                    <component v-if="hasPropEditor(propName, editorName)" :is="getPropEditor(propName, editorName)"
                               :designer="designer" :selected-widget="selectedWidget"
                               :option-model="optionModel"></component>
                  </template>
                </el-collapse-item>

                <el-collapse-item name="2" v-if="showCollapse(advProps)"
                                  :title="i18nt('designer.setting.advancedSetting')">
                  <template v-for="(editorName, propName) in advProps">
                    <component v-if="hasPropEditor(propName, editorName)" :is="getPropEditor(propName, editorName)"
                               :designer="designer" :selected-widget="selectedWidget"
                               :option-model="optionModel"></component>
                  </template>
                </el-collapse-item>

                <el-collapse-item name="3" v-if="showEventCollapse() && showCollapse(eventProps)"
                                  :title="i18nt('designer.setting.eventSetting')">
                  <template v-for="(editorName, propName) in eventProps">
                    <component v-if="hasPropEditor(propName, editorName)" :is="getPropEditor(propName, editorName)"
                               :designer="designer" :selected-widget="selectedWidget" :option-model="optionModel"
                               :event-handled="getEventHandled(propName)"></component>
                  </template>
                </el-collapse-item>
              </el-collapse>

            </el-form>
          </template>

          <template v-if="(!!designer.selectedWidget && !!designer.selectedWidget.category)">
            <el-form :model="optionModel" size="small" label-position="left" label-width="120px" class="setting-form"
                     @submit.prevent>
              <el-collapse v-model="widgetActiveCollapseNames" class="setting-collapse">
                <el-collapse-item name="1" v-if="showCollapse(commonProps)"
                                  :title="i18nt('designer.setting.commonSetting')">
                  <template v-for="(editorName, propName) in commonProps">
                    <component v-if="hasPropEditor(propName, editorName)" :is="getPropEditor(propName, editorName)"
                               :designer="designer" :selected-widget="selectedWidget"
                               :option-model="optionModel"></component>
                  </template>
                </el-collapse-item>

                <el-collapse-item name="2" v-if="showCollapse(advProps)"
                                  :title="i18nt('designer.setting.advancedSetting')">
                  <template v-for="(editorName, propName) in advProps">
                    <component v-if="hasPropEditor(propName, editorName)" :is="getPropEditor(propName, editorName)"
                               :designer="designer" :selected-widget="selectedWidget"
                               :option-model="optionModel"></component>
                  </template>
                </el-collapse-item>

                <el-collapse-item name="3" v-if="showEventCollapse() && showCollapse(eventProps)"
                                  :title="i18nt('designer.setting.eventSetting')">
                  <template v-for="(editorName, propName) in eventProps">
                    <component v-if="hasPropEditor(propName, editorName)" :is="getPropEditor(propName, editorName)"
                               :designer="designer" :selected-widget="selectedWidget" :option-model="optionModel"
                               :event-handled="getEventHandled(propName)"></component>
                  </template>
                </el-collapse-item>
              </el-collapse>
            </el-form>
          </template>

          <template v-if="!designer.selectedWidget">
            <el-empty :description="i18nt('designer.hint.noSelectedWidgetHint')"></el-empty>
          </template>

        </el-scrollbar>
      </el-tab-pane>

      <el-tab-pane v-if="!!designer" :label="i18nt('designer.hint.formSetting')" name="2">
        <el-scrollbar class="setting-scrollbar">
          <form-setting :designer="designer" :form-config="formConfig"></form-setting>
        </el-scrollbar>
      </el-tab-pane>

      <el-tab-pane :label="i18nt('designer.setting.dataSource')" name="3">
        <el-scrollbar class="ds-setting-scrollbar">
          <data-source-setting :designer="designer" :form-config="formConfig">
          </data-source-setting>
        </el-scrollbar>
      </el-tab-pane>
      <el-tab-pane label="样式" name="4">
        <el-scrollbar class="ds-setting-scrollbar">
          <style-setting :designer="designer"
                         :selected-widget="selectedWidget"
                         :showCollapse="showCollapse"
                         :getPropEditor="getPropEditor"
                         :hasPropEditor="hasPropEditor"
          ></style-setting>
        </el-scrollbar>
      </el-tab-pane>
    </el-tabs>

    <div v-if="showWidgetEventDialogFlag" class=""
    >
      <!--      <el-dialog :title="i18nt('designer.setting.editWidgetEventHandler')" v-model="showWidgetEventDialogFlag"
                       :show-close="true" class="drag-dialog small-padding-dialog" append-to-body
                       :close-on-click-modal="false" :close-on-press-escape="false" :destroy-on-close="true">
              <el-alert type="info" :closable="false" ></el-alert>-->
      <code-editor
        :event-param="eventHeader"
        :mode="'javascript'"
        :readonly="false"
        v-model="eventHandlerCode"
        v-model:show="showWidgetEventDialogFlag"
        ref="ecEditor">
        <template #footer>
          <el-button @click="showWidgetEventDialogFlag = false">
            {{ i18nt('designer.hint.cancel') }}
          </el-button>
          <el-button type="primary" @click="saveEventHandler">
            {{ i18nt('designer.hint.confirm') }}
          </el-button>
        </template>
      </code-editor>
      <!--        <el-alert type="info" :closable="false" title="}"></el-alert>-->

      <!--      </el-dialog>-->
    </div>

  </el-container>
</template>

<script>
import CodeEditor from '@/components/code-editor/index'
import PropertyEditors from './property-editor/index'
import FormSetting from './form-setting'
import DataSourceSetting from './data-source-setting'
import WidgetProperties from './propertyRegister'
import i18n from '@/utils/i18n'
import emitter from '@/utils/emitter'
import { propertyRegistered } from '@/components/form-designer/setting-panel/propertyRegister'
import StyleSetting from '@/components/form-designer/setting-panel/style-setting/index.vue'
import eventBus from '@/utils/event-bus.js'

const { COMMON_PROPERTIES, ADVANCED_PROPERTIES, EVENT_PROPERTIES } = WidgetProperties

export default {
  name: 'SettingPanel',
  componentName: 'SettingPanel',
  mixins: [i18n, emitter],
  components: {
    StyleSetting,
    CodeEditor,
    FormSetting,
    DataSourceSetting,
    ...PropertyEditors,
  },
  props: {
    designer: Object,
    selectedWidget: Object,
    formConfig: Object,
    globalDsv: {
      type: Object,
      default: () => ({}),
    },
  },
  provide() {
    return {
      isSubFormChildWidget: () => this.subFormChildWidgetFlag,
      getGlobalDsv: () => this.globalDsv, // 全局数据源变量
    }
  },
  inject: ['getDesignerConfig'],
  data() {
    return {
      designerConfig: this.getDesignerConfig(),

      activeTab: '2',
      widgetActiveCollapseNames: ['1', '2', '3'],
      formActiveCollapseNames: ['1', '2'],

      commonProps: COMMON_PROPERTIES,
      advProps: ADVANCED_PROPERTIES,
      eventProps: EVENT_PROPERTIES,

      showWidgetEventDialogFlag: false,
      eventHandlerCode: '',
      curEventName: '',
      eventHeader: '',

      subFormChildWidgetFlag: false,
    }
  },
  computed: {
    optionModel: {
      get() {
        return this.selectedWidget.options
      },

      set(newValue) {
        this.selectedWidget.options = newValue
      },
    },

  },
  watch: {
    'designer.selectedWidget': {
      handler(val) {
        /*  if (!!val) {
           this.activeTab = "1"
         } */
      },
    },

    'selectedWidget.options': {  //组件属性变动后，立即保存表单JSON！！
      deep: true,
      handler() {
        this.designer.saveCurrentHistoryStep()
      },
    },

    formConfig: {
      deep: true,
      handler() {
        this.designer.saveCurrentHistoryStep()
      },
    },

  },
  created() {
    this.on$('editEventHandler', (eventParams) => {
      this.editEventHandler(eventParams[0], eventParams[1])
    })

    this.designer.handleEvent('form-css-updated', (cssClassList) => {
      this.designer.setCssClassList(cssClassList)
    })

    //监听字段组件选中事件
    this.designer.handleEvent('field-selected', (parentWidget) => {
      this.subFormChildWidgetFlag = !!parentWidget && (parentWidget.type === 'sub-form')
    })
  },
  mounted() {
    if (!this.designer.selectedWidget) {
      this.activeTab = '2'
    } else {
      this.activeTab = '1'
    }
  },
  methods: {
    getEventHandled(eventName) {
      return !!this.optionModel[eventName] && (this.optionModel[eventName].length > 0)
    },

    showEventCollapse() {
      if (this.designerConfig['eventCollapse'] === undefined) {
        return true
      }

      return !!this.designerConfig['eventCollapse']
    },

    hasPropEditor(propName, editorName) {
      if (!editorName) {
        return false
      }

      /* alert组件注册了两个type属性编辑器，跳过第一个type属性编辑器，只显示第二个alert-type属性编辑器！！ */
      if (propName.indexOf('-') <= -1) {
        let uniquePropName = this.selectedWidget.type + '-' + propName
        if (propertyRegistered(uniquePropName)) {
          return false
        }
      }

      let originalPropName = propName.replace(this.selectedWidget.type + '-', '')  //去掉组件名称前缀-，如果有的话！！
      return this.designer.hasConfig(this.selectedWidget, originalPropName)
    },

    getPropEditor(propName, editorName) {
      let originalPropName = propName.replace(this.selectedWidget.type + '-', '')  //去掉组件名称前缀-，如果有的话！！
      let ownPropEditorName = `${this.selectedWidget.type}-${originalPropName}-editor`
      //console.log(ownPropEditorName, this.$options.components[ownPropEditorName])
      if (!!this.$options.components[ownPropEditorName]) {  //局部注册的属性编辑器组件
        return ownPropEditorName
      }

      //return !!this.$root.$options.components[ownPropEditorName] ? ownPropEditorName : editorName  //Vue2全局注册的属性编辑器组件
      // console.log('propName', propName);
      return !!this.$root.$.appContext.components[ownPropEditorName] ? ownPropEditorName : editorName  //Vue3全局注册的属性编辑器组件
    },

    showCollapse(propsObj) {
      let result = false
      // console.log('showCollapse', propsObj);
      for (let propName in propsObj) {
        if (!propsObj.hasOwnProperty(propName)) {
          continue
        }

        if (this.hasPropEditor(propName, propsObj[propName])) {
          result = true
          break
        }
      }

      return result
    },

    editEventHandler(eventName, eventParams) {
      this.curEventName = eventName
      this.eventHeader = `${this.optionModel.name}.${eventName}(${eventParams.join(', ')}) {`
      this.eventHandlerCode = this.selectedWidget.options[eventName] || ''

      // 设置字段校验函数示例代码
      if ((eventName === 'onValidate') && (!this.optionModel['onValidate'])) {
        this.eventHandlerCode = '  /* sample code */\n  /*\n  if ((value > 100) || (value < 0)) {\n    callback(new Error(\'error message\'))  //fail\n  } else {\n    callback();  //pass\n  }\n  */'
      }

      this.showWidgetEventDialogFlag = true
    },

    saveEventHandler() {
      /*const codeHints = this.$refs.ecEditor.getEditorAnnotations()
      let syntaxErrorFlag = false
      if (!!codeHints && (codeHints.length > 0)) {
        codeHints.forEach((chItem) => {
          if (chItem.type === 'error') {
            syntaxErrorFlag = true
          }
        })

        if (syntaxErrorFlag) {
          this.$message.error(this.i18nt('designer.setting.syntaxCheckWarning'))
          return
        }
      }*/
      eventBus.$emit('hasSyntaxErrors', (hasSyntaxErrors) => {
        if (!hasSyntaxErrors) {
          this.selectedWidget.options[this.curEventName] = this.eventHandlerCode
          this.showWidgetEventDialogFlag = false
        }
      })
    },

  },
}
</script>

<style lang="scss" scoped>
.panel-container {
  padding: 0 8px;

  :deep(.ep-tabs__item) {
    padding: 10px
  }
}

.setting-scrollbar {
  height: 100%;

  :deep(.ep-scrollbar__wrap) {
    overflow-x: hidden; /* IE浏览器隐藏水平滚动条箭头！！ */
  }
}

.ds-setting-scrollbar {
  /*width: 284px;*/
  :deep(.ep-scrollbar__wrap) {
    overflow-x: hidden; /* IE浏览器隐藏水平滚动条箭头！！ */
  }
}

.setting-collapse {
  :deep(.ep-collapse-item__content) {
    padding-bottom: 6px;
  }

  :deep(.ep-collapse-item__header) {
    font-style: italic;
    font-weight: bold;
  }
}

.setting-form {
  :deep(.ep-form-item__label) {
    font-size: 13px;
    //text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
  }

  :deep(.ep-form-item--small.ep-form-item) {
    margin-bottom: 10px;
  }
}

/* 隐藏Chrome浏览器中el-input数字输入框右侧的上下调整小箭头 */
:deep(.hide-spin-button) input::-webkit-outer-spin-button,
:deep(.hide-spin-button) input::-webkit-inner-spin-button {
  -webkit-appearance: none !important;
}

/* 隐藏Firefox浏览器中el-input数字输入框右侧的上下调整小箭头 */
:deep(.hide-spin-button) input[type="number"] {
  -moz-appearance: textfield;
}

:deep(.custom-divider.ep-divider--horizontal) {
  margin: 10px 0;
}

:deep(.custom-divider-margin-top.ep-divider--horizontal) {
  margin: 20px 0;
}

.small-padding-dialog {
  :deep(.ep-dialog__body) {
    padding: 6px 15px 12px 15px;
  }
}

:deep(.header-small-mb .ep-drawer__header) {
  margin-bottom: 6px;
}

:deep(.header-small-mb .ep-drawer__body) {
  padding: 12px;
}

:deep(.ep-button.button-text-highlight) {
  font-weight: bold;
  color: var(--ep-color-primary);
}

</style>

<style lang="scss">
.ds-setting-drawer {
  right: 320px !important;
}

</style>
